#include "main.h"

#include <stdint.h>
#include <stdio.h>
// #include <windows.h>
#include "../functional_test/functional_test.h"
#include "../windows_service/os_ticket/os_ticket.h"
#include "../windows_service/tlog/tlog.h"

#define tieta_v4

#ifdef tieta_v4
#include "tieta_v4/tieta_v4.h"
#endif  // tieta_v4

#ifdef tieta_zk_v1_3
#include "tieta_zk_v1_3/tieta_zk_v1_3.h"
#endif  // tieta_zk_v1_3

#define TAG "MAIN"

static uint8_t send_buf[256];

static unsigned short ModBusCRC16(const void* s, int n) {
  unsigned short c = 0xffff;
  for (int k = 0; k < n; k++) {
    unsigned short b = (((unsigned char*)s)[k]);
    for (char i = 0; i < 8; i++) {
      c = ((b ^ c) & 1) ? (c >> 1) ^ 0xA001 : (c >> 1);
      b >>= 1;
    }
  }
  return (c << 8) | (c >> 8);
}

static void ModBusCRC16_test() {
  uint8_t buffer[] = {0X01, 0X03, 0X03, 0XE8, 0X00, 0X0C};
  int     ret      = 0;
  typ_iow temp;

  ret = ModBusCRC16(buffer, (sizeof(buffer) / sizeof(uint8_t)));
  printf("ret:%d\n", ret);
  temp.word_16 = ret;
  printf("LOW:0X%x,HIGH:0X%x\n", temp.byte[0], temp.byte[1]);
}

#ifdef tieta_v4
static void tieta_function_code_01_test(void) {
  /* 读取多个开关量测试 */
  // uint8_t cmd_buffer[] = {0X01, 0X01, 0X00, 0X00, 0X00, 0X05, 0XFC, 0X09};//读5个数据
  // uint8_t cmd_buffer[] = {0X01, 0X01, 0X00, 0X00, 0X00, 0X08, 0X3D, 0XCC};//读8个数据
  // uint8_t cmd_buffer[] = {0X01, 0X01, 0X00, 0X00, 0X00, 0X0A, 0XBC, 0X0D};//读10个数据
  // uint8_t cmd_buffer[] = {0X01, 0X01, 0X00, 0X00, 0X00, 0X14, 0X3C, 0X05};  // 读20个数据
  uint8_t cmd_buffer[] = {0X01, 0X01, 0X00, 0X00, 0X00, 0X34, 0X3D, 0XDD};  // 铁塔协议中的示例读取52个数据

  tieta_receive(cmd_buffer, (sizeof(cmd_buffer) / sizeof(uint8_t)));
}

static void tieta_function_code_03_test(void) {
  /* 读取多个寄存器测试 */
  uint8_t cmd_buffer[] = {0X01, 0X03, 0X03, 0XE8, 0X00, 0X0C, 0XC5, 0XBF};
  register_table_device_id_set();
  tieta_receive(cmd_buffer, (sizeof(cmd_buffer) / sizeof(uint8_t)));
}

static void tieta_error_code_01_test(void) {
  /* 无效报文类型错误码测试,功能码4是不存在的 */
  uint8_t cmd_buffer[] = {0X01, 0X04, 0X03, 0XE8, 0X00, 0X0C, 0X70, 0X7F};
  tieta_receive(cmd_buffer, (sizeof(cmd_buffer) / sizeof(uint8_t)));
}

static void tieta_error_code_02_test(void) {
  /* 无效的数据地址，包含数据长度越界错误码测试,注册的表格数据没那么多 */
  uint8_t cmd_buffer[] = {0X01, 0X03, 0X03, 0XE8, 0X03, 0XE8, 0XC5, 0X04};
  tieta_receive(cmd_buffer, (sizeof(cmd_buffer) / sizeof(uint8_t)));
}

static void tieta_function_6_test(void) {
  uint8_t cmd_buffer_read[]  = {0X01, 0X03, 0X00, 0X00, 0X00, 0X01, 0X84, 0X0A};
  uint8_t cmd_buffer_write[] = {0X01, 0X06, 0X00, 0X00, 0X20, 0X60, 0X90, 0X22};

  // 读取要写入的寄存器
  tieta_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
  /* 写入单个寄存器 */
  tieta_receive(cmd_buffer_write, (sizeof(cmd_buffer_write) / sizeof(uint8_t)));
  // 读取写入后的寄存器数据
  tieta_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
}

static void tieta_function_5_test(void) {
  uint8_t cmd_buffer_read[]  = {0X01, 0X01, 0X00, 0X00, 0X00, 0X01, 0XFD, 0XCA};
  uint8_t cmd_buffer_write[] = {0X01, 0X05, 0X00, 0X00, 0XFF, 0X00, 0X8C, 0X3A};

  // 读取要写入的开关量
  tieta_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
  /* 写入单个开关量 */
  tieta_receive(cmd_buffer_write, (sizeof(cmd_buffer_write) / sizeof(uint8_t)));
  // 读取写入后的开关量数据
  tieta_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
}

static void tieta_function_5_error_test(void) {
  /* 写入错误开关量 */
  uint8_t cmd_buffer_read[]  = {0X01, 0X01, 0X00, 0X00, 0X00, 0X01, 0XFD, 0XCA};
  uint8_t cmd_buffer_write[] = {0X01, 0X05, 0X00, 0X00, 0XFF, 0X80, 0X8D, 0X9A};

  // 读取要写入的开关量
  tieta_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
  /* 写入单个开关量 */
  tieta_receive(cmd_buffer_write, (sizeof(cmd_buffer_write) / sizeof(uint8_t)));
  // 读取写入后的开关量数据
  tieta_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
}

static void tieta_function_10_test() {
  // 与铁塔协议V4示例一致
  uint8_t cmd_buffer_read[]  = {0X01, 0X03, 0X00, 0X02, 0X00, 0X03, 0XA4, 0X0B};
  uint8_t cmd_buffer_write[] = {0X01, 0X10, 0X00, 0X02, 0X00, 0X03, 0X06, 0X01, 0X90, 0XFE, 0X0C, 0X02, 0XBC, 0X77, 0XBC};

  // 读取要写入的寄存器
  tieta_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
  /* 写入单个寄存器 */
  tieta_receive(cmd_buffer_write, (sizeof(cmd_buffer_write) / sizeof(uint8_t)));
  // 读取写入后的寄存器数据
  tieta_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
}

static void tieta_function_0F_test() {
  // 与铁塔协议V4示例一致
  uint8_t cmd_buffer_read[]  = {0X01, 0X01, 0X00, 0X00, 0X00, 0X09, 0XFC, 0X0C};
  uint8_t cmd_buffer_write[] = {0X01, 0X0F, 0X00, 0X00, 0X00, 0X09, 0X02, 0X5C, 0X01, 0X1D, 0XBC};

  // 读取要写入的寄存器
  tieta_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
  /* 写入单个寄存器 */
  tieta_receive(cmd_buffer_write, (sizeof(cmd_buffer_write) / sizeof(uint8_t)));
  // 读取写入后的寄存器数据
  tieta_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
}
#endif  // tieta_v4

#ifdef tieta_zk_v1_3
static void tieta_zk_v1_3_function_0A_test() {
  /* 读取电池概要信息 */
  uint8_t cmd_buffer_read[] = {0X01, 0X0A, 0XA0, 0X01, 0X00, 0X19, 0X2B, 0XC1};
  tieta_zk_v1_3_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
  tieta_zk_v1_3_send(send_buf, 256);
}

static void tieta_zk_v1_3_function_0A_test2() {
  /* 读取电池实时状态 */
  uint8_t cmd_buffer_read[] = {0X01, 0X0A, 0X00, 0X00, 0X00, 0X26, 0X18, 0X11};
  tieta_zk_v1_3_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
  tieta_zk_v1_3_send(send_buf, 256);
}

static void tieta_zk_v1_3_function_0B_test() {
  // 写入年月日时分秒
  uint8_t cmd_buffer_read[]  = {0X01, 0X0A, 0X00, 0X22, 0X00, 0X04, 0X38, 0X02};
  uint8_t cmd_buffer_write[] = {0X01, 0X0B, 0X00, 0X22, 0X00, 0X04, 0X07, 0XE7, 0X0C, 0X1F, 0X14, 0X3B, 0X3B, 0X00, 0X07, 0X18};
  tieta_zk_v1_3_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
  tieta_zk_v1_3_send(send_buf, 256);

  tieta_zk_v1_3_receive(cmd_buffer_write, (sizeof(cmd_buffer_write) / sizeof(uint8_t)));
  tieta_zk_v1_3_send(send_buf, 256);

  tieta_zk_v1_3_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
  tieta_zk_v1_3_send(send_buf, 256);
}

static void tieta_zk_v1_3_function_switch_test() {
  uint8_t cmd_buffer_read[]  = {0x01, 0x0A, 0xB0, 0x01, 0x00, 0x06, 0x6E, 0XC9};
  uint8_t cmd_buffer_write[] = {0X01, 0X0B, 0XB0, 0X01, 0X00, 0X01, 0X00, 0X00, 0X4D, 0X37};
  tieta_zk_v1_3_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
  tieta_zk_v1_3_send(send_buf, 256);

  tieta_zk_v1_3_receive(cmd_buffer_write, (sizeof(cmd_buffer_write) / sizeof(uint8_t)));
  tieta_zk_v1_3_send(send_buf, 256);

  tieta_zk_v1_3_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
  tieta_zk_v1_3_send(send_buf, 256);
}

static void tieta_zk_v1_3_function_sn_code_test() {
  uint8_t cmd_buffer_read[] = {0X01, 0X0A, 0X03, 0XE8, 0X00, 0X0C, 0X19, 0XBE};
  tieta_zk_v1_3_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
  tieta_zk_v1_3_send(send_buf, 256);
}

static void tieta_zk_v1_3_function_error_test() {
  uint8_t cmd_buffer_read[] = {0X01, 0X0A, 0X03, 0X00, 0X00, 0X10, 0X98, 0X43};
  tieta_zk_v1_3_receive(cmd_buffer_read, (sizeof(cmd_buffer_read) / sizeof(uint8_t)));
  tieta_zk_v1_3_send(send_buf, 256);
}
#endif  // tieta_zk_v1_3

void main() {
#ifdef tieta_v4
  // ModBusCRC16_test();
  tieta_init();
  // tieta_function_code_03_test();
  // tieta_error_code_01_test();
  // tieta_error_code_02_test();
  // tieta_function_code_01_test();
  // tieta_function_6_test();
  // tieta_function_5_test();
  // tieta_function_5_error_test();
  tieta_function_10_test();
  // tieta_function_0F_test();
#endif  // tieta_v4

#ifdef tieta_zk_v1_3
  tieta_zk_v1_3_init();
  tieta_zk_v1_3_function_0A_test();
  tieta_zk_v1_3_function_0A_test2();
  tieta_zk_v1_3_function_0B_test();
  tieta_zk_v1_3_function_switch_test();
  tieta_zk_v1_3_function_sn_code_test();
  tieta_zk_v1_3_function_error_test();
#endif  // tieta_zk_v1_3

  os_create_thread(functional_test_log, 1000);

  os_thread_start();
}